package com.zyl.blog.CogniSphere.service;

import com.alibaba.fastjson2.JSON;
import com.zyl.blog.CogniSphere.config.SparkAiProperties;
import com.zyl.blog.CogniSphere.model.SparkRequest;
import com.zyl.blog.CogniSphere.model.SparkResponse;
import com.zyl.blog.common.domain.ai.dto.TableMeta;
import com.zyl.blog.common.utils.Extreme.LogUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;

import java.net.URI;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @version v1.0
 * @ProjectName: Personal_Blog_Server
 * @Package: com.zyl.blog.CogniSphere.service.SparkAiSqlService
 * @ClassName: SparkAiSqlService
 * @Description: 智能SQL生成业务
 * @Author FinalFantasy
 * @Date 2025/8/15-10:37
 */
@Service
@RequiredArgsConstructor
public class SparkAiSqlService {
    private final WebClient webClient;
    private final SparkAiProperties properties;

    /**
     * 生成创建表的SQL语句
     */
    public String generateCreateTableSql(TableMeta tableMeta) {
        /* 构建提示词（Prompt Engineering） */
        String prompt = buildCreateTablePrompt(tableMeta);
        LogUtil.info("生成SQL提示词: [{}]", prompt);

        /* 调用星火AI接口 */
        String aiResponse = callSparkAi(prompt);
        LogUtil.info("AI返回结果: [{}]", aiResponse);

        /* 提取并清洗SQL（去除多余文本） */
        return extractSqlFromResponse(aiResponse);
    }

    /**
     * 从TableMeta中提取关键信息作为提示词摘要，用于日志记录
     */
    public static String extractPromptFromTableMeta(Object tableMetaObj) {
        if (!(tableMetaObj instanceof TableMeta tableMeta)) {
            return "无效的表结构参数";
        }

        StringBuilder prompt = new StringBuilder();
        prompt.append("表名: ").append(tableMeta.getTableName());
        prompt.append(", 字段数: ").append(tableMeta.getColumns() != null ? tableMeta.getColumns().size() : 0);

        if (tableMeta.getPrimaryKeys() != null && !tableMeta.getPrimaryKeys().isEmpty()) {
            prompt.append(", 主键: ").append(String.join(",", tableMeta.getPrimaryKeys()));
        }

        return prompt.toString();
    }

    /**
     * 构建创建表的提示词
     */
    private String buildCreateTablePrompt(TableMeta tableMeta) {
        return "请帮我生成创建MySQL表的SQL语句，要求如下：\n" +
                "1. 表名：" + tableMeta.getTableName() + "，表注释：" + tableMeta.getComment() + "\n" +
                "2. 字段信息：\n" +
                tableMeta.getColumns().stream()
                        .map(col -> "- " + col.getColumnName() + "：类型" + col.getJdbcType() +
                                (col.getLength() != null ? "(" + col.getLength() + ")" : "") +
                                (col.getNullable() ? "，允许为空" : "，不允许为空") +
                                (col.getAutoIncrement() ? "，自增" : "") +
                                "，注释：" + col.getComment())
                        .collect(Collectors.joining("\n")) + "\n" +
                "3. 主键：" + String.join(",", tableMeta.getPrimaryKeys()) + "\n" +
                (tableMeta.getIndexes() != null ? "4. 索引：\n" +
                        tableMeta.getIndexes().stream()
                                .map(idx -> "- " + (idx.getUnique() ? "唯一索引" : "普通索引") +
                                        idx.getIndexName() + "：字段" + String.join(",", idx.getColumnNames()))
                                .collect(Collectors.joining("\n")) + "\n" : "") +
                "5. 要求：\n" +
                "- 使用MySQL 8.0语法\n" +
                "- 表名和字段名用反引号包裹，防止关键字冲突\n" +
                "- 只返回SQL语句，不要额外解释";
    }

    /**
     * 调用星火AI WebSocket接口
     */
    private String callSparkAi(String prompt) {
        try {
            /* 构建请求参数 */
            SparkRequest request = new SparkRequest();
            request.setHeader(new SparkRequest.Header(properties.getAppId(), properties.getApiKey(), properties.getDomain()));
            request.setParameter(new SparkRequest.Parameter(properties.getModel()));
            request.setPayload(new SparkRequest.Payload(
                    new SparkRequest.Message(new SparkRequest.Content("user", prompt))
            ));

            /* WebSocket异步调用 */
            CompletableFuture<String> responseFuture = new CompletableFuture<>();
            StringBuilder responseBuilder = new StringBuilder();

            webClient.get()
                    .uri(uriBuilder -> uriBuilder
                            .scheme("wss")
                            .host(URI.create(properties.getBaseUrl()).getHost())
                            .path(URI.create(properties.getBaseUrl()).getPath())
                            .queryParam("appid", properties.getAppId())
                            .queryParam("api_key", properties.getApiKey())
                            .queryParam("api_secret", properties.getApiSecret())
                            .build())
                    .header("Authorization", "Bearer fwghZGkMweKGTXLqnXDZ:ZivzaaJwEFoegVSFDsJP")
                    .header("Content-Type", "application/json")
                    .exchangeToFlux(clientResponse -> clientResponse.bodyToFlux(String.class))
                    .subscribe(
                            /* 接收消息 */
                            message -> {
                                SparkResponse response = JSON.parseObject(message, SparkResponse.class);
                                if (response.getPayload() != null && response.getPayload().getChoices() != null) {
                                    String content = response.getPayload().getChoices().getText().getFirst().getContent();
                                    responseBuilder.append(content);
                                }
                                /* 判断是否结束 */
                                if (response.getHeader() != null && response.getHeader().getCode() != 0) {
                                    responseFuture.complete(responseBuilder.toString());
                                }
                            },
                            /* 错误处理*/
                            responseFuture::completeExceptionally,
                            /* 完成处理 */
                            () -> responseFuture.complete(responseBuilder.toString())
                    );

            /* 等待结果 */
            return responseFuture.get(properties.getTimeout(), TimeUnit.MILLISECONDS);
        } catch (Exception e) {
            LogUtil.error("调用星火AI失败: [{}]", null, e);
            throw new RuntimeException("生成SQL失败：" + e.getMessage());
        }
    }

    /**
     * 从AI响应中提取SQL（去除多余格式）
     */
    private String extractSqlFromResponse(String response) {
        /* 去除代码块标记（如```sql ... ```） */
        if (response.contains("```")) {
            String[] parts = response.split("```");
            return parts.length >= 2 ? parts[1].replace("sql", "").trim() : response;
        }
        return response.trim();
    }
}